package com.jingogo.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.digest.BCrypt;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jingogo.common.BusinessException;
import com.jingogo.entity.User;
import com.jingogo.mapper.UserMapper;
import com.jingogo.service.UserService;
import com.jingogo.util.JwtUtil;
import com.jingogo.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;

/**
 * 用户服务实现类
 * 
 * @author jingogo
 * @since 2024-01-01
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void register(User user, String verifyCode) {
        // 验证验证码
        if (!verifyCode(user.getPhone(), verifyCode, "register")) {
            throw new BusinessException("验证码错误或已过期");
        }

        // 检查用户名是否存在
        if (isUsernameExists(user.getUsername())) {
            throw new BusinessException("用户名已存在");
        }

        // 检查手机号是否存在
        if (isPhoneExists(user.getPhone())) {
            throw new BusinessException("手机号已存在");
        }

        // 密码加密
        user.setPassword(BCrypt.hashpw(user.getPassword(), BCrypt.gensalt()));
        user.setStatus(1);
        user.setVerifiedStatus(0);
        user.setWalletBalance(java.math.BigDecimal.ZERO);
        user.setPoints(0);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());

        // 保存用户
        save(user);
        log.info("用户注册成功: {}", user.getUsername());
    }

    @Override
    public String login(String username, String password) {
        User user;
        if (StringUtils.hasText(username) && username.contains("@")) {
            // 邮箱登录
            user = getOne(new LambdaQueryWrapper<User>().eq(User::getEmail, username));
        } else if (StringUtils.hasText(username) && username.matches("^1[3-9]\\d{9}$")) {
            // 手机号登录
            user = getOne(new LambdaQueryWrapper<User>().eq(User::getPhone, username));
        } else {
            // 用户名登录
            user = getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
        }

        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        if (user.getStatus() == 0) {
            throw new BusinessException("用户已被禁用");
        }

        if (!BCrypt.checkpw(password, user.getPassword())) {
            throw new BusinessException("密码错误");
        }

        // 更新最后登录时间
        user.setLastLoginTime(LocalDateTime.now());
        updateById(user);

        // 生成JWT token
        String token = jwtUtil.generateToken(user.getId().toString());
        log.info("用户登录成功: {}", user.getUsername());
        return token;
    }

    @Override
    public void sendVerifyCode(String phone, String type) {
        // 生成6位验证码
        String code = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
        
        // 存储到Redis，5分钟过期
        String key = "verify_code:" + type + ":" + phone;
        redisUtil.set(key, code, 300);

        // TODO: 调用腾讯云短信服务发送验证码
        log.info("发送验证码到手机号: {}, 验证码: {}, 类型: {}", phone, code, type);
    }

    @Override
    public boolean verifyCode(String phone, String code, String type) {
        String key = "verify_code:" + type + ":" + phone;
        String savedCode = redisUtil.getString(key);
        
        if (savedCode != null && savedCode.equals(code)) {
            redisUtil.delete(key);
            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserInfo(User user) {
        User existingUser = getById(user.getId());
        if (existingUser == null) {
            throw new BusinessException("用户不存在");
        }

        // 只允许更新部分字段
        existingUser.setNickname(user.getNickname());
        existingUser.setAvatar(user.getAvatar());
        existingUser.setGender(user.getGender());
        existingUser.setBirthday(user.getBirthday());
        existingUser.setUpdateTime(LocalDateTime.now());

        updateById(existingUser);
        log.info("用户信息更新成功: {}", user.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void verifyIdentity(Long userId, String realName, String idCard) {
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // TODO: 调用第三方实名认证服务
        user.setRealName(realName);
        user.setIdCard(idCard);
        user.setVerifiedStatus(1);
        user.setUpdateTime(LocalDateTime.now());

        updateById(user);
        log.info("用户实名认证成功: {}", userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void inviteUser(Long inviterId, String phone) {
        User inviter = getById(inviterId);
        if (inviter == null) {
            throw new BusinessException("邀请人不存在");
        }

        // TODO: 发送邀请短信，建立邀请关系
        log.info("用户邀请成功: 邀请人ID={}, 被邀请手机号={}", inviterId, phone);
    }

    @Override
    public IPage<User> getUserPage(Integer pageNum, Integer pageSize, String keyword) {
        Page<User> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        
        if (StringUtils.hasText(keyword)) {
            wrapper.like(User::getUsername, keyword)
                  .or()
                  .like(User::getPhone, keyword)
                  .or()
                  .like(User::getNickname, keyword);
        }
        
        wrapper.orderByDesc(User::getCreateTime);
        return page(page, wrapper);
    }

    @Override
    public User getUserById(Long id) {
        return getById(id);
    }

    @Override
    public User getUserByPhone(String phone) {
        return userMapper.selectByPhone(phone);
    }

    @Override
    public boolean isPhoneExists(String phone) {
        return userMapper.countByPhone(phone) > 0;
    }

    @Override
    public boolean isUsernameExists(String username) {
        return userMapper.countByUsername(username) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addUserPoints(Long userId, Integer points) {
        User user = getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        user.setPoints(user.getPoints() + points);
        updateById(user);
        log.info("用户 {} 积分增加 {} 成功", userId, points);
    }
}